/*

XML处理
@author
[2011-11-21]
selectSingleNode
selectNodes

*/

// 加载XML文件并返回XML文档节点
// return:    成功时返回一个对象（同步模式下返回xml文档对象，异步模式下返回操作对象），失败时返回空。
// xmlUrl: xml文件的url。
// funcAsync: 回调函数. function onload(xmlDoc, isError){ ... }
function xml_loadFile(xmlUrl, funcAsync)
{
    var xmlDoc = null;
    var isChrome = false;
    var asyncIs = (null!=funcAsync);    // 是否是异步加载。当funcAsync不为空时，使用异步加载，否则是同步加载。
    
    // 检查参数
    if (""==xmlUrl)    return null;
    if (asyncIs)
    {
        if ("function"!=typeof(funcAsync))    return null;
    }
    
    // 创建XML对象
    try
    {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");    // Support IE
    }
    catch(ex)
    {
    }
    if (null==xmlDoc)
    {
        try
        {
            // Support Firefox, Mozilla, Opera, etc
            xmlDoc = document.implementation.createDocument("", "", null);    // 创建一个空的 XML 文档对象。
        }
        catch(ex)
        {
        }
    }
    if (null==xmlDoc)    return null;
    
    // 加载XML文档
    xmlDoc.async = asyncIs;
    if (asyncIs)
    {
        if(window.ActiveXObject)
        {
            xmlDoc.onreadystatechange = function(){
                if(xmlDoc.readyState == 4)
                {
                    var isError = false;
                    if (null!=xmlDoc.parseError)
                    {
                        isError = (0!=xmlDoc.parseError.errorCode);    // 0成功, 非0失败。
                    }
                    funcAsync(xmlDoc, isError);
                }
            }
        }
        else
        {
            xmlDoc.onload = function(){
                funcAsync(xmlDoc, false);
            }
        }
    }
    try
    {
        xmlDoc.load(xmlUrl);
    }
    catch(ex)
    {
        // alert(ex.message)    // 如果浏览器是Chrome，则会catch这个异常：Object # (a Document) has no method "load"
        isChrome = true;
        xmlDoc = null;
    }
    if (isChrome)
    {
        var xhr = new XMLHttpRequest();
        if (asyncIs)    // 异步
        {
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4)
                {
                    funcAsync(xhr.responseXML, xhr.status != 200);
                }
            }
            xhr.open("GET", xmlUrl, true);
            try    // 异步模式下，由回调函数处理错误。
            {
                xhr.send(null);
            }
            catch(ex)
            {
                funcAsync(null, true);
                return null;
            }
            return xhr;    // 注意：返回的是XMLHttpRequest。建议异步模式下仅用null测试返回值。
        }
        else    // 同步
        {
            xhr.open("GET", xmlUrl, false);
            xhr.send(null);    // 同步模式下，由调用者处理异常
            xmlDoc = xhr.responseXML;
        }
    }
    
    return xmlDoc;
}

// 使用XSLT把XML文档转换为一个字符串。
function xml_transformNode(xmlDoc, xslDoc)
{
    if (null==xmlDoc)    return "";
    if (null==xslDoc)    return "";
    
    if (window.ActiveXObject)    // IE
    {
        return xmlDoc.transformNode(xslDoc);
    }
    else    // FireFox, Chrome
    {
        //定义XSLTProcesor对象
        var xsltProcessor=new XSLTProcessor();
        xsltProcessor.importStylesheet(xslDoc);
        // transformToDocument方式
        var result=xsltProcessor.transformToDocument(xmlDoc);
        var xmls=new XMLSerializer();
        var rt = xmls.serializeToString(result);
        return rt;
    }
}

// 得到节点的文本
function xml_text(xmlNode)
{
    if (null==xmlNode)    return "";
    var rt;
    if (window.ActiveXObject)    // IE
    {
        rt = xmlNode.text;
    }
    else
    {
        // FireFox, Chrome, ...
        rt = xmlNode.textContent;
    }
    if (null==rt)    rt=xmlNode.nodeValue;    // XML DOM
    return rt;
}

//设置节点文本
function xml_setText(xmlNode,text){
	if (null==xmlNode)    return "";
    if (window.ActiveXObject)    // IE
    {
        xmlNode.text = text;
    }else{
		xmlNode.textContent = text;
	}
}

/**
 * 获取节点的xml数据
 * @param {Object} node
 */
function xml_convertNodeToString(node){
	if(window.ActiveXObject){
		return node.xml;
	}else{
		return (new XMLSerializer()).serializeToString(node);
	}
}

function xml_convertStringToNode(sXML){
	if(window.ActiveXObject){
		var xn = new ActiveXObject("microsoft.xmldom");
		if(sXML != null && sXML !="" && sXML){
			xn.loadXML(sXML);
		} 
		return xn.documentElement;
	}else{
		return new DOMParser().parseFromString(sXML, "text/xml").documentElement;
	}
}

/**
 * 创建xml节点
 */
function xml_createNode(sNodeName){
	if(window.ActiveXObject){
		var xn = new ActiveXObject("microsoft.xmldom");
		if(sNodeName != null && sNodeName !="" && sNodeName){
			xn.loadXML("<"+sNodeName+"></"+sNodeName+">");
		} 
		return xn.documentElement;
	}else{
		return document.implementation.createDocument("",sNodeName, null).documentElement;
	}
}

function getEventSrcElement(){
	var theEvent = window.event || arguments.callee.caller.arguments[0];
	var srcElement = theEvent.srcElement;
	if (!srcElement)
	{
	       srcElement = theEvent.target;
	}
	return srcElement;
}

// 添加方法。为了兼容FireFox、Chrome。
if (!window.ActiveXObject)
{
    XMLDocument.prototype.selectSingleNode = Element.prototype.selectSingleNode = function (xpath)
    {
        var  x = this.selectNodes(xpath)
        if ( ! x || x.length < 1 ) return   null ;
        return  x[ 0 ];
    }
    XMLDocument.prototype.selectNodes = Element.prototype.selectNodes = function (xpath)
    {
        var  xpe  =   new  XPathEvaluator();
        var  nsResolver  =  xpe.createNSResolver( this.ownerDocument  ==   null?this.documentElement :  this.ownerDocument.documentElement);
        var  result  =  xpe.evaluate(xpath,  this , nsResolver,  0 ,  null );
        var  found  =  [];
        var  res;
        while  (res  =  result.iterateNext())
            found.push(res);
        return  found;
    }
}

//兼容Firefox
//function __firefox(){
//    HTMLElement.prototype.__defineGetter__("runtimeStyle", __element_style);
//    window.constructor.prototype.__defineGetter__("event", __window_event);
//    Event.prototype.__defineGetter__("srcElement", __event_srcElement);
//}
//function __element_style(){
//    return this.style;
//}
//function __window_event(){
//    return __window_event_constructor();
//}
//function __event_srcElement(){
//    return this.target;
//}
//function __window_event_constructor(){
//    if(document.all){
//        return window.event;
//    }
//    var _caller = __window_event_constructor.caller;
//    while(_caller!=null){
//        var _argument = _caller.arguments[0];
//        if(_argument){
//            var _temp = _argument.constructor;
//            if(_temp.toString().indexOf("Event")!=-1){
//                return _argument;
//            }
//        }
//        _caller = _caller.caller;
//    }
//    return null;
//}
//if(window.addEventListener){
//    __firefox();
//}
//
//if (document.implementation.hasFeature("XPath", "3.0"))
//{
//	if (typeof XMLDocument == "undefined") { XMLDocument = Document; }
//	XMLDocument.prototype.selectNodes = function (cXPathString, xNode)
//	{
//		if (!xNode) { xNode = this; }
//		var oNSResolver = this.createNSResolver(this.documentElement)
//		var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
//		var aResult = [];
//		for (var i = 0; i < aItems.snapshotLength; i++) { aResult[i] = aItems.snapshotItem(i); }
//		return aResult;
//	}
//	XMLDocument.prototype.selectSingleNode = function (cXPathString, xNode)
//	{
//		if (!xNode) { xNode = this; }
//		var xItems = this.selectNodes(cXPathString, xNode);
//		if (xItems.length > 0) { return xItems[0]; }
//		else { return null; }
//	}
//	Element.prototype.selectNodes = function (cXPathString)
//	{
//		if (this.ownerDocument.selectNodes) { return this.ownerDocument.selectNodes(cXPathString, this); }
//		else { throw "For XML Elements Only"; }
//	}
//	Element.prototype.selectSingleNode = function (cXPathString)
//	{
//		if (this.ownerDocument.selectSingleNode) { return this.ownerDocument.selectSingleNode(cXPathString, this); }
//		else { throw "For XML Elements Only"; }
//	}
//}

